﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using IEx.Common;
using IEx.Model.Partials;
using IEx.Utilities;

namespace IEx.ParserBuilder.Amthuc365
{
    public class AmthucParser : IHtmlParser
    {
        public void Parse(SourceItem item, string html, Action<Model.Partials.Announcement> attachResultItem, Action<SourceItem> attachNewItemSource)
        {
            try
            {
                string startHtml = "class=\"restaurant_search_list mt20\"";
                string endHtml = "class=\"col2_2\"";
                string remainHtml = Utility.GetHtmlBody(html, startHtml, endHtml);
                List<Announcement> detectedAnnouncements = new List<Announcement>();
                Uri newUri = Utility.CreateNewUriForNextPage(item.Url);

                if (!string.IsNullOrEmpty(remainHtml))
                {
                    Regex regRestaurants = new Regex("<div class=\"r\">.*?</div>.*?</div>");
                    MatchCollection mRestaurants = regRestaurants.Matches(remainHtml);
                    for (int i = 0; i < mRestaurants.Count; i++)
                    {
                        string title = string.Empty;
                        string address = string.Empty;
                        string phone = string.Empty;
                        string linkDetail = string.Empty;
                        string description = string.Empty;
                        string restaurantHtml = mRestaurants[i].Value.Trim();

                        Regex regTitle = new Regex("<h3 class=\"title mb5\">.*?</h3>");
                        Match mTitle = regTitle.Match(restaurantHtml);
                        if (mTitle.Success)
                        {
                            string titleHtml = mTitle.Value.Trim();
                            title = RegexUtility.ExtractTextFromHtmlTag(titleHtml).Trim();
                            string link = RegexUtility.ExtractHyperlink(titleHtml);
                            if (!string.IsNullOrEmpty(link))
                            {
                                linkDetail = new Uri(newUri, link).ToString();
                            }
                        }

                        Regex regAddress = new Regex("<address class=\"mb5 wrap\">.*?</address>");
                        Match mAddress = regAddress.Match(restaurantHtml);
                        if (mAddress.Success)
                        {
                            string addressHtml = mAddress.Value.Trim();
                            address = RegexUtility.ExtractTextFromHtmlTag(addressHtml);
                        }

                        Regex regPhone = new Regex("<div class=\"line wrap mb5\">.*?</div>");
                        Match mPhone = regPhone.Match(restaurantHtml);
                        if (mPhone.Success)
                        {
                            string phoneHtml = mPhone.Value.Trim();
                            phone = RegexUtility.ExtractTextFromHtmlTag(phoneHtml);
                        }

                        Regex regDescription = new Regex("<ul class=\"highlight\">.*?</ul>");
                        Match mDescription=regDescription.Match(restaurantHtml);
                        if (mDescription.Success)
                        {
                            string descriptionHtml = mDescription.Value.Trim();
                            description = RegexUtility.ExtractTextFromHtmlTag(descriptionHtml);
                        }
                        if (!string.IsNullOrEmpty(title) && !string.IsNullOrEmpty(address))
                        {
                            Announcement ann = new Announcement();
                            ann.InsertedDate = DateTime.Now;
                            ann.SourceCode = item.SearchCode;
                            ann.Title = title;
                            ann.Message = description;
                            ann.SourceCode = item.SourceCode;
                            ann.SocialNetwork.RestaurantInfo.ContactInfo.Address = address;
                            ann.SocialNetwork.RestaurantInfo.ContactInfo.HomePhone = phone;
                            ann.SourceId = item.SourceId;
                            detectedAnnouncements.Add(ann);
                        }
                    }
                    Regex regNextPage = new Regex("<a class=\"current page\".*?</a><a.*?</a>");
                    Match mNextPage=regNextPage.Match(remainHtml);
                    if (mNextPage.Success)
                    {
                        string nextPageHtml = mNextPage.Value.Trim();
                        string link = RegexUtility.ExtractHyperlink(nextPageHtml);
                        if (!string.IsNullOrEmpty(link))
                            item.Url = new Uri(newUri, link).ToString();                        
                    }
                }
                // check if has next page 
                // next page counts as a new request, so it needed insert into request queue

                if (CheckNextPageAmthuc365(item.Url))
                {
                    SourceItem nItem = new SourceItem(item.Url, item.LangId, item.SourceCode, item.SearchCode, item.SourceId, item.DateTimeFormat);
                    if (!string.IsNullOrEmpty(item.RequestBuilderType))
                        nItem.RequestBuilderType = item.RequestBuilderType;

                    if (!string.IsNullOrEmpty(item.HtmlParserType))
                        nItem.HtmlParserType = item.HtmlParserType;

                    nItem.PrevResponseHtml = html;
                    attachNewItemSource(nItem);
                }

                // insert into download queue when no error in parsing
                foreach (Announcement ann in detectedAnnouncements)
                {
                    attachResultItem(ann);
                }

                // if this request is fail request in previous scanning, 
                // remove it when success in current scanning
                if (item.FailId > 0)
                    Utility.DeleteFailRequests(item.FailId);
            }
            catch (Exception ex)
            {
                // if has an error, save fail request to next time scanning
                if (item.FailId == 0)
                {
                    item.FailId = DateTime.Now.Ticks;
                    Utility.SaveFailRequests(item);
                }

                // then write log
                string message = string.Format(@"
            Company code:   {0}
            HTML Parsing:   Fail
            Request URL:    {1}
            Search key:     {2}", item.SourceCode, item.Url, item.SearchCode);
                Logger.WriteError(message, ex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        private static bool CheckNextPageAmthuc365(string response)
        {
            bool hasNextPage = !string.IsNullOrEmpty(response) && string.Compare(response, "javascript:void();") != 0;
            return hasNextPage;
        }
    }
}
